package com.plum.admin.config.security.permission;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.plum.admin.modules.sys.entity.SysMenu;
import com.plum.admin.modules.sys.service.ISysMenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;
import org.springframework.util.PathMatcher;

import java.util.*;
import java.util.stream.Collectors;

/**
 * TODO
 *
 * @author 子丶沫
 * @version 1.0
 * @date 2021/8/13 17:55
 */
@Slf4j
@Component
public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
    @Autowired
    private ISysMenuService menuService;
    @Autowired
    private PathMatcher pathMatcher;

    private Map<String, Collection<ConfigAttribute>> map = null;

    public void loadResourceDefine(){
        map = new HashMap<>(16);
        Collection<ConfigAttribute> configAttributes;
        ConfigAttribute cfg;
        // 获取启用的权限操作请求
        List<SysMenu> permissions = menuService.list(Wrappers.<SysMenu>lambdaQuery())
                .stream().filter(menu->StrUtil.isNotBlank(menu.getPermission()))
                .collect(Collectors.toList());
        for(SysMenu menu : permissions) {
            configAttributes = new ArrayList<>();
            cfg = new SecurityConfig(menu.getPermission());
            //作为MyAccessDecisionManager类的decide的第三个参数
            configAttributes.add(cfg);
            //用权限的path作为map的key，用ConfigAttribute的集合作为value
            map.put(menu.getPath(), configAttributes);
        }
    }
    @Override
    public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
        if (map == null) {
            loadResourceDefine();
        }
        // Object中包含用户请求request
        String url = ((FilterInvocation) o).getRequestUrl();
        for (String resURL : map.keySet()) {
            if (StrUtil.isNotBlank(resURL) && pathMatcher.match(resURL, url)) {
                return map.get(resURL);
            }
        }
        return null;
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}
